//
//  Ezwave.h
//  ezLogin
//
//  Created by 刘跃龙 on 2/5/17.
//  Copyright © 2017 absolutemobile. All rights reserved.
//

#ifndef Ezwave_h
#define Ezwave_h
#include "cocos2d.h"
#if HAVEEZWAVE
#include "EzTools.h"
#include "json.h"
#include <string>
#include <list>
#include <vector>
#include <functional>
#include "Manager.h"
#include "Options.h"
#include "Driver.h"
#include "Notification.h"
#include "value_classes/Value.h"
#include "Defs.h"
#include "linux_lock.h"

EZ_BEGIN

class Ezwave
{
public:
    typedef struct
    {
        uint32			m_homeId;
        uint8			m_nodeId;
        bool			m_isPolled;
        std::list<OpenZWave::ValueID>	m_values;
    } NodeInfo;
    typedef struct
    {
        OpenZWave::Notification::NotificationType type;
        MYJson::Value data;
    } EventInfo;
public:
    void update();
//    void setEventCallback(std::function<void(Ezwave::EventInfo)> callback){ m_callback = callback;};
    MYJson::Value getNodesInfo();
    void removeOtherNode();
    MYJson::Value getNodeInfo(uint8 nodeId);
    bool addNode();
    bool removeNode();
    bool cancelControllerCommand();
    bool hasNodeFailed(std::string nodeIdStr);
    bool removeFailedNode(std::string nodeIdStr);
    bool requestNetworkUpdate();
    bool writeConfig();
    bool reset();
    bool setConfigParam(std::string nodeIdStr, std::string paramStr, std::string valueStr, std::string sizeStr);
    bool requestAllConfigParams( std::string nodeIdStr );
    bool setValue(std::string nodeIdStr,std::string instanceStr,std::string classIdStr,std::string indexStr,std::string valueStr);
    bool refreshValue(std::string nodeIdStr,std::string instanceStr,std::string classIdStr,std::string indexStr);
    bool refreshAllValue();
    bool refreshNodeValue(std::string nodeIdStr);
    bool getChangeVerified(std::string nodeIdStr,std::string instanceStr,std::string classIdStr,std::string indexStr);
    bool setChangeVerified(std::string nodeIdStr,std::string instanceStr,std::string classIdStr,std::string indexStr);
    
    static void destory();
private:
    MYJson::Value getJsonFromNodeInfo(Ezwave::NodeInfo *nodeInfo);
    MYJson::Value getJsonFromValueID(OpenZWave::ValueID valueId);
    static std::string getControllerCommandName(uint8 command);
    static std::string getValueTyepName(OpenZWave::ValueID::ValueType type);
    static std::string getNotificationTypeName(int type);
    static std::string getControllerCommandState(uint8 state);
    static std::string getControllerCommandError(uint8 error);
    Ezwave::NodeInfo* getNodeInfoFromNodeId(uint8 nodeId);
private:
    static OpenZWave::Options* s_Options;
    static OpenZWave::Manager* s_Manager;
    static std::list<Ezwave*> s_pointList;
    static std::string s_configFilePath;
public:
    std::string m_zwavePath;
    bool m_initComplete;
    bool m_initFailed;
    std::list<Ezwave::NodeInfo*> m_nodes;
    std::vector<Ezwave::EventInfo> m_events;
    LinuxLock m_evnetMutex;
    LinuxLock m_criticalSection;
    LinuxLock m_initMutex;
public:
    Ezwave(std::string serial,std::string userPath);
    ~Ezwave();
private:
    std::string m_serial;
    uint32 m_homeId;
//    std::function<void(Ezwave::EventInfo)> m_callback;
    static void OnNotification(OpenZWave::Notification const* _notification,void* _context);
    void pushEvent(Ezwave::EventInfo event);
private://保证回调中指针不为野指针 addPointList delPointList isExist
    static void addPointList(Ezwave* point){
        Ezwave::s_pointList.push_back(point);
    };
    static void delPointList(Ezwave* point){
        for(std::list<Ezwave*>::iterator it = Ezwave::s_pointList.begin();it != Ezwave::s_pointList.end();it++){
            if(*it == point){
                Ezwave::s_pointList.erase(it);
                return;
            }
        }
    };
    static bool isExist(Ezwave* point){
        for(std::list<Ezwave*>::iterator it = s_pointList.begin();it != s_pointList.end();it++){
            if(*it == point) return true;
        }
        return false;
    }
};

EZ_END
#endif
#endif /* Ezwave_h */
